home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / ddj0492.zip / DFLT11.ZIP / NORMAL.C < prev    next >
Text File  |  1992-02-29  |  34KB  |  1,071 lines

  1. /* ------------- normal.c ------------ */
  2.  
  3. #include "dflat.h"
  4.  
  5. #ifdef INCLUDE_MULTI_WINDOWS
  6. static void near PaintOverLappers(WINDOW wnd);
  7. static void near PaintUnderLappers(WINDOW wnd);
  8. #endif
  9.  
  10. static BOOL InsideWindow(WINDOW, int, int);
  11. static void TerminateMoveSize(void);
  12. static void SaveBorder(RECT);
  13. static void RestoreBorder(RECT);
  14. #ifdef INCLUDE_MINIMIZE
  15. static RECT PositionIcon(WINDOW);
  16. #endif
  17. static void near dragborder(WINDOW, int, int);
  18. static void near sizeborder(WINDOW, int, int);
  19. static int px = -1, py = -1;
  20. static int diff;
  21. static BOOL conditioning;
  22. static struct window dwnd = {DUMMY, NULL, NULL, NormalProc,
  23.                                 {-1,-1,-1,-1}};
  24. static int *Bsave;
  25. static int Bht, Bwd;
  26. BOOL WindowMoving;
  27. BOOL WindowSizing;
  28. /* -------- array of class definitions -------- */
  29. CLASSDEFS classdefs[] = {
  30.     #undef ClassDef
  31.     #define ClassDef(c,b,p,a) {b,p,a},
  32.     #include "classes.h"
  33. };
  34. WINDOW HiddenWindow;
  35.  
  36. /* --------- CREATE_WINDOW Message ---------- */
  37. static void CreateWindowMsg(WINDOW wnd)
  38. {
  39.     WINDOW pwnd = GetParent(wnd);
  40.     AppendFocusWindow(wnd);
  41.     if (!SendMessage(NULL, MOUSE_INSTALLED, 0, 0))
  42.         ClearAttribute(wnd, VSCROLLBAR | HSCROLLBAR);
  43.     if (TestAttribute(wnd, SAVESELF) && isVisible(wnd))
  44.         GetVideoBuffer(wnd);
  45.     if (pwnd != NULL)    {
  46.         pwnd->Children = realloc(pwnd->Children,
  47.             sizeof(WINDOW) * (pwnd->ChildCt+1));
  48.         *(pwnd->Children+pwnd->ChildCt++) = wnd;
  49.     }
  50. }
  51.  
  52. /* --------- SHOW_WINDOW Message ---------- */
  53. static void ShowWindowMsg(WINDOW wnd, PARAM p1, PARAM p2)
  54. {
  55.     if ((GetParent(wnd) == NULL || isVisible(GetParent(wnd))) &&
  56.             !conditioning)    {
  57.         BOOL wasVisible = isVisible(wnd);
  58.         WINDOW cwnd;
  59.         int i;
  60.         SetVisible(wnd);
  61.         if (TestAttribute(wnd, SAVESELF) && !wasVisible)    {
  62.             if (wnd->videosave != NULL)    {
  63.                 SwapVideoBuffer(wnd);
  64.                 return;
  65.             }
  66.             else 
  67.                 GetVideoBuffer(wnd);
  68.         }
  69.         SendMessage(wnd, PAINT, 0, TRUE);
  70.         SendMessage(wnd, BORDER, 0, 0);
  71.         /* --- show the children of this window --- */
  72.         for (i = 0; i < wnd->ChildCt; i++)    {
  73.             cwnd = *(wnd->Children + i);
  74.             if (cwnd->condition != ISCLOSING)
  75.                 SendMessage(cwnd, SHOW_WINDOW, p1, p2);
  76.         }
  77.     }
  78. }
  79.  
  80. /* --------- HIDE_WINDOW Message ---------- */
  81. static void HideWindowMsg(WINDOW wnd, BOOL FullHide)
  82. {
  83.     if (isVisible(wnd) && !conditioning)    {
  84.         ClearVisible(wnd);
  85.         /* --- paint what this window covered --- */
  86.         if (wnd->videosave != NULL)    {
  87.             if (FullHide)
  88.                 RestoreVideoBuffer(wnd);
  89.             else
  90.                 SwapVideoBuffer(wnd);
  91.         }
  92. #ifdef INCLUDE_MULTI_WINDOWS
  93.         else
  94.             PaintOverLappers(wnd);
  95. #endif
  96.     }
  97. }
  98.  
  99. /* --------- KEYBOARD Message ---------- */
  100. static BOOL KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  101. {
  102.     if (WindowMoving || WindowSizing)    {
  103.         /* -- move or size a window with keyboard -- */
  104.         int x, y;
  105.         x=WindowMoving?GetLeft(&dwnd):GetRight(&dwnd);
  106.         y=WindowMoving?GetTop(&dwnd):GetBottom(&dwnd);
  107.         switch ((int)p1)    {
  108.             case ESC:
  109.                 TerminateMoveSize();
  110.                 return TRUE;
  111.             case UP:
  112.                 if (y)
  113.                     --y;
  114.                 break;
  115.             case DN:
  116.                 if (y < SCREENHEIGHT-1)
  117.                     y++;
  118.                 break;
  119.             case FWD:
  120.                 if (x < SCREENWIDTH-1)
  121.                     x++;
  122.                 break;
  123.             case BS:
  124.                 if (x)
  125.                     --x;
  126.                 break;
  127.             case '\r':
  128.                 SendMessage(wnd,BUTTON_RELEASED,x,y);
  129.             default:
  130.                 return TRUE;
  131.         }
  132.         /* -- use the mouse functions to move/size - */
  133.         SendMessage(wnd, MOUSE_CURSOR, x, y);
  134.         SendMessage(wnd, MOUSE_MOVED, x, y);
  135.         return TRUE;
  136.     }
  137.     switch ((int)p1)    {
  138.         case F1:
  139.             SendMessage(wnd, COMMAND, ID_HELP, 0);
  140.             return TRUE;
  141.         case ' ':
  142.             if ((int)p2 & ALTKEY)
  143.                 if (TestAttribute(wnd, HASTITLEBAR))
  144.                     if (TestAttribute(wnd, CONTROLBOX))
  145.                         BuildSystemMenu(wnd);
  146.             return TRUE;
  147.         case CTRL_F4:
  148.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  149.             SkipSystemWindows(FALSE);
  150.             return TRUE;
  151.         default:
  152.             break;
  153.     }
  154.     return FALSE;
  155. }
  156.  
  157. /* --------- COMMAND Message ---------- */
  158. static void CommandMsg(WINDOW wnd, PARAM p1)
  159. {
  160.     switch ((int)p1)    {
  161.         case ID_HELP:
  162.             DisplayHelp(wnd,ClassNames[GetClass(wnd)]);
  163.             break;
  164. #ifdef INCLUDE_RESTORE
  165.         case ID_SYSRESTORE:
  166.             SendMessage(wnd, RESTORE, 0, 0);
  167.             break;
  168. #endif
  169.         case ID_SYSMOVE:
  170.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  171.                 (PARAM) &dwnd);
  172.             SendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
  173.                 (PARAM) &dwnd);
  174.             SendMessage(wnd, MOUSE_CURSOR,
  175.                 GetLeft(wnd), GetTop(wnd));
  176.             WindowMoving = TRUE;
  177.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  178.             break;
  179.         case ID_SYSSIZE:
  180.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  181.                 (PARAM) &dwnd);
  182.             SendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
  183.                 (PARAM) &dwnd);
  184.             SendMessage(wnd, MOUSE_CURSOR,
  185.                 GetRight(wnd), GetBottom(wnd));
  186.             WindowSizing = TRUE;
  187.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  188.             break;
  189. #ifdef INCLUDE_MINIMIZE
  190.         case ID_SYSMINIMIZE:
  191.             SendMessage(wnd, MINIMIZE, 0, 0);
  192.             break;
  193. #endif
  194. #ifdef INCLUDE_MAXIMIZE
  195.         case ID_SYSMAXIMIZE:
  196.             SendMessage(wnd, MAXIMIZE, 0, 0);
  197.             break;
  198. #endif
  199.         case ID_SYSCLOSE:
  200.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  201.             break;
  202.         default:
  203.             break;
  204.     }
  205. }
  206.  
  207. static void ReFocus(WINDOW wnd, WINDOW Self)
  208. {
  209.     WINDOW pwnd = GetParent(wnd);
  210.     WINDOW cwnd;
  211.     int i;
  212.     if (GetClass(wnd) != POPDOWNMENU)    {
  213.         /* refocus all ancestors down to but not including APPLICATION */
  214.         if (Self != (WINDOW)-1 && pwnd != NULL)
  215.             if (GetClass(pwnd) != APPLICATION)
  216.                 ReFocus(pwnd, wnd);
  217.         /* refocus all children of this window */
  218.            for (i = 0; i < wnd->ChildCt; i++)    {
  219.                cwnd = *(wnd->Children+i);
  220.                if (cwnd != Self)
  221.                    ReFocus(cwnd, (WINDOW) -1);
  222.         }
  223.     }
  224.     /* remove window from Focus list */
  225.     RemoveFocusWindow(wnd);
  226.     /* move window to end of Focus list */
  227.     AppendFocusWindow(wnd);
  228. }
  229.  
  230. /* --------- SETFOCUS Message ---------- */
  231. static void SetFocusMsg(WINDOW wnd, PARAM p1)
  232. {
  233.     if (p1 && inFocus != wnd)    {
  234.         /* ---- setting focus ------ */
  235.         WINDOW pwnd = GetParent(wnd);
  236.         int Redraw = !TestAttribute(wnd, SAVESELF) && isVisible(wnd);
  237.         AddAttribute(wnd, VISIBLE);
  238. #ifdef INCLUDE_MULTI_WINDOWS
  239.         if (GetClass(pwnd) == APPLICATION)
  240.             /* -- if no children, do not need selective redraw --- */
  241.             if (wnd->ChildCt == 0)
  242.                 Redraw = FALSE;
  243. #endif
  244.         SendMessage(inFocus, SETFOCUS, FALSE, 0);
  245.         inFocus = wnd;
  246.         if (Redraw)    {
  247. #ifdef INCLUDE_MULTI_WINDOWS
  248.             PaintUnderLappers(GetAncestor(wnd));
  249. #endif
  250.             ReFocus(wnd, NULL);
  251.             SendMessage(wnd, BORDER, 0, 0);
  252.         }
  253.         else    {
  254.             ReFocus(wnd, NULL);
  255.             if (GetClass(wnd) == POPDOWNMENU ||
  256.                 pwnd == NULL ||
  257.                     isDerivedFrom(pwnd, DIALOG) ||
  258.                         isDerivedFrom(pwnd, APPLICATION))
  259.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  260.             else
  261.                 SendMessage(pwnd, SHOW_WINDOW, 0, 0);
  262.         }
  263.     }
  264.     else if (!p1 && inFocus == wnd)    {
  265.         /* -------- clearing focus --------- */
  266.         inFocus = NULL;
  267.         SendMessage(wnd, BORDER, 0, 0);
  268.     }
  269. }
  270.  
  271. /* --------- DOUBLE_CLICK Message ---------- */
  272. static void DoubleClickMsg(WINDOW wnd, PARAM p1, PARAM p2)
  273. {
  274.     int mx = (int) p1 - GetLeft(wnd);
  275.     int my = (int) p2 - GetTop(wnd);
  276.     if (!WindowSizing && !WindowMoving)
  277.         if (HitControlBox(wnd, mx, my))
  278.             PostMessage(wnd, CLOSE_WINDOW, 0, 0);
  279. }
  280.  
  281. /* --------- LEFT_BUTTON Message ---------- */
  282. static void LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  283. {
  284.     int mx = (int) p1 - GetLeft(wnd);
  285.     int my = (int) p2 - GetTop(wnd);
  286.     if (WindowSizing || WindowMoving)
  287.         return;
  288.     if (HitControlBox(wnd, mx, my))    {
  289.         BuildSystemMenu(wnd);
  290.         return;
  291.     }
  292.     if (my == 0 && mx > -1 && mx < WindowWidth(wnd))  {
  293.         /* ---------- hit the top border -------- */
  294.         if (TestAttribute(wnd, MINMAXBOX) &&
  295.                 TestAttribute(wnd, HASTITLEBAR))  {
  296.             if (mx == WindowWidth(wnd)-2)    {
  297.                 if (wnd->condition != ISRESTORED)
  298.                     /* --- hit the restore box --- */
  299.                     SendMessage(wnd, RESTORE, 0, 0);
  300. #ifdef INCLUDE_MAXIMIZE
  301.                 else
  302.                     /* --- hit the maximize box --- */
  303.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  304. #endif
  305.                 return;
  306.             }
  307. #ifdef INCLUDE_MINIMIZE
  308.             if (mx == WindowWidth(wnd)-3)    {
  309.                 /* --- hit the minimize box --- */
  310.                 if (wnd->condition != ISMINIMIZED)
  311.                     SendMessage(wnd, MINIMIZE, 0, 0);
  312.                 return;
  313.             }
  314. #endif
  315.         }
  316. #ifdef INCLUDE_MAXIMIZE
  317.         if (wnd->condition == ISMAXIMIZED)
  318.             return;
  319. #endif
  320.         if (TestAttribute(wnd, MOVEABLE))    {
  321.             WindowMoving = TRUE;
  322.             px = mx;
  323.             py = my;
  324.             diff = (int) mx;
  325.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  326.                 (PARAM) &dwnd);
  327.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  328.         }
  329.         return;
  330.     }
  331.     if (mx == WindowWidth(wnd)-1 &&
  332.             my == WindowHeight(wnd)-1)    {
  333.         /* ------- hit the resize corner ------- */
  334. #ifdef INCLUDE_MINIMIZE
  335.         if (wnd->condition == ISMINIMIZED)
  336.             return;
  337. #endif
  338.         if (!TestAttribute(wnd, SIZEABLE))
  339.             return;
  340. #ifdef INCLUDE_MAXIMIZE
  341.         if (wnd->condition == ISMAXIMIZED)    {
  342.             if (GetParent(wnd) == NULL)
  343.                 return;
  344.             if (TestAttribute(GetParent(wnd),HASBORDER))
  345.                 return;
  346.             /* ----- resizing a maximized window over a
  347.                     borderless parent ----- */
  348.             wnd = GetParent(wnd);
  349.         }
  350. #endif
  351.         WindowSizing = TRUE;
  352.         SendMessage(wnd, CAPTURE_MOUSE,
  353.             TRUE, (PARAM) &dwnd);
  354.         dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  355.     }
  356. }
  357.  
  358. /* --------- MOUSE_MOVED Message ---------- */
  359. static BOOL MouseMovedMsg(WINDOW wnd, PARAM p1, PARAM p2)
  360. {
  361.     if (WindowMoving)    {
  362.         int leftmost = 0, topmost = 0,
  363.             bottommost = SCREENHEIGHT-2,
  364.             rightmost = SCREENWIDTH-2;
  365.         int x = (int) p1 - diff;
  366.         int y = (int) p2;
  367.         if (GetParent(wnd) != NULL &&
  368.                 !TestAttribute(wnd, NOCLIP))    {
  369.             WINDOW wnd1 = GetParent(wnd);
  370.             topmost    = GetClientTop(wnd1);
  371.             leftmost   = GetClientLeft(wnd1);
  372.             bottommost = GetClientBottom(wnd1);
  373.             rightmost  = GetClientRight(wnd1);
  374.         }
  375.         if (x < leftmost || x > rightmost ||
  376.                 y < topmost || y > bottommost)    {
  377.             x = max(x, leftmost);
  378.             x = min(x, rightmost);
  379.             y = max(y, topmost);
  380.             y = min(y, bottommost);
  381.             SendMessage(NULL,MOUSE_CURSOR,x+diff,y);
  382.         }
  383.         if (x != px || y != py)    {
  384.             px = x;
  385.             py = y;
  386.             dragborder(wnd, x, y);
  387.         }
  388.         return TRUE;
  389.     }
  390.     if (WindowSizing)    {
  391.         sizeborder(wnd, (int) p1, (int) p2);
  392.         return TRUE;
  393.     }
  394.     return FALSE;
  395. }
  396.  
  397. #ifdef INCLUDE_MAXIMIZE
  398. /* --------- MAXIMIZE Message ---------- */
  399. static void MaximizeMsg(WINDOW wnd)
  400. {
  401.     RECT rc = {0, 0, 0, 0};
  402.     RECT holdrc;
  403.     holdrc = wnd->RestoredRC;
  404.     rc.rt = SCREENWIDTH-1;
  405.     rc.bt = SCREENHEIGHT-1;
  406.     if (GetParent(wnd))
  407.         rc = ClientRect(GetParent(wnd));
  408.     wnd->oldcondition = wnd->condition;
  409.     wnd->condition = ISMAXIMIZED;
  410.     SendMessage(wnd, HIDE_WINDOW, TRUE, 0);
  411.     conditioning = TRUE;
  412.     SendMessage(wnd, MOVE,
  413.         RectLeft(rc), RectTop(rc));
  414.     SendMessage(wnd, SIZE,
  415.         RectRight(rc), RectBottom(rc));
  416.     conditioning = FALSE;
  417.     if (wnd->restored_attrib == 0)
  418.         wnd->restored_attrib = wnd->attrib;
  419.     ClearAttribute(wnd, SHADOW);
  420.     SendMessage(wnd, SHOW_WINDOW, 0, 0);
  421.     wnd->RestoredRC = holdrc;
  422. }
  423. #endif
  424.  
  425. #ifdef INCLUDE_MINIMIZE
  426. /* --------- MINIMIZE Message ---------- */
  427. static void MinimizeMsg(WINDOW wnd)
  428. {
  429.     RECT rc;
  430.     RECT holdrc;
  431.  
  432.     holdrc = wnd->RestoredRC;
  433.     rc = PositionIcon(wnd);
  434.     wnd->oldcondition = wnd->condition;
  435.     wnd->condition = ISMINIMIZED;
  436.     SendMessage(wnd, HIDE_WINDOW, TRUE, 0);
  437.     conditioning = TRUE;
  438.     SendMessage(wnd, MOVE,
  439.         RectLeft(rc), RectTop(rc));
  440.     SendMessage(wnd, SIZE,
  441.         RectRight(rc), RectBottom(rc));
  442.     SetPrevFocus(wnd);
  443.     conditioning = FALSE;
  444.     if (wnd->restored_attrib == 0)
  445.         wnd->restored_attrib = wnd->attrib;
  446.     ClearAttribute(wnd,
  447.         SHADOW | SIZEABLE | HASMENUBAR |
  448.         VSCROLLBAR | HSCROLLBAR);
  449.     SendMessage(wnd, SHOW_WINDOW, 0, 0);
  450.     wnd->RestoredRC = holdrc;
  451. }
  452. #endif
  453.  
  454. #ifdef INCLUDE_RESTORE
  455. /* --------- RESTORE Message ---------- */
  456. static void RestoreMsg(WINDOW wnd)
  457. {
  458.     RECT holdrc;
  459.     holdrc = wnd->RestoredRC;
  460.     wnd->oldcondition = wnd->condition;
  461.     wnd->condition = ISRESTORED;
  462.     SendMessage(wnd, HIDE_WINDOW, TRUE, 0);
  463.     wnd->attrib = wnd->restored_attrib;
  464.     wnd->restored_attrib = 0;
  465.     conditioning = TRUE;
  466.     SendMessage(wnd, MOVE, wnd->RestoredRC.lf,
  467.         wnd->RestoredRC.tp);
  468.     wnd->RestoredRC = holdrc;
  469.     SendMessage(wnd, SIZE, wnd->RestoredRC.rt,
  470.         wnd->RestoredRC.bt);
  471.     SendMessage(wnd, SETFOCUS, TRUE, 0);
  472.     conditioning = FALSE;
  473.     SendMessage(wnd, SHOW_WINDOW, 0, 0);
  474. }
  475. #endif
  476.  
  477. /* --------- MOVE Message ---------- */
  478. static void MoveMsg(WINDOW wnd, PARAM p1, PARAM p2)
  479. {
  480.     WINDOW cwnd;
  481.     BOOL wasVisible = isVisible(wnd);
  482.     int xdif = (int) p1 - wnd->rc.lf;
  483.     int ydif = (int) p2 - wnd->rc.tp;
  484.     int i;
  485.  
  486.     if (xdif == 0 && ydif == 0)
  487.         return;
  488.     if (wasVisible)
  489.         SendMessage(wnd, HIDE_WINDOW, 0, 0);
  490.     wnd->rc.lf = (int) p1;
  491.     wnd->rc.tp = (int) p2;
  492.     wnd->rc.rt = GetLeft(wnd)+WindowWidth(wnd)-1;
  493.     wnd->rc.bt = GetTop(wnd)+WindowHeight(wnd)-1;
  494.     if (wnd->condition == ISRESTORED)
  495.         wnd->RestoredRC = wnd->rc;
  496.     for (i = 0; i < wnd->ChildCt; i++)    {
  497.         cwnd = *(wnd->Children + i);
  498.         SendMessage(cwnd, MOVE, cwnd->rc.lf+xdif, cwnd->rc.tp+ydif);
  499.     }
  500.     if (wasVisible)
  501.         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  502. }
  503.  
  504. /* --------- SIZE Message ---------- */
  505. static void SizeMsg(WINDOW wnd, PARAM p1, PARAM p2)
  506. {
  507.     BOOL wasVisible = isVisible(wnd);
  508.     WINDOW cwnd;
  509.     int i;
  510.     RECT rc;
  511.     int xdif = (int) p1 - wnd->rc.rt;
  512.     int ydif = (int) p2 - wnd->rc.bt;
  513.  
  514.     if (xdif == 0 && ydif == 0)
  515.         return;
  516.     if (wasVisible)
  517.         SendMessage(wnd, HIDE_WINDOW, TRUE, 0);
  518.     wnd->rc.rt = (int) p1;
  519.     wnd->rc.bt = (int) p2;
  520.     wnd->ht = GetBottom(wnd)-GetTop(wnd)+1;
  521.     wnd->wd = GetRight(wnd)-GetLeft(wnd)+1;
  522.  
  523.     if (wnd->condition == ISRESTORED)
  524.         wnd->RestoredRC = WindowRect(wnd);
  525.  
  526.     rc = ClientRect(wnd);
  527. #ifdef INCLUDE_MAXIMIZE
  528.     for (i = 0; i < wnd->ChildCt; i++)    {
  529.         cwnd = *(wnd->Children + i);
  530.         if (cwnd->condition == ISMAXIMIZED)
  531.             SendMessage(cwnd, SIZE, RectRight(rc), RectBottom(rc));
  532.     }
  533. #endif
  534.     if (wasVisible)
  535.         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  536. }
  537.  
  538. /* --------- CLOSE_WINDOW Message ---------- */
  539. static void CloseWindowMsg(WINDOW wnd)
  540. {
  541.     WINDOW pwnd = GetParent(wnd);
  542.     wnd->condition = ISCLOSING;
  543.     if (wnd->PrevMouse != NULL)
  544.         SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  545.     if (wnd->PrevKeyboard != NULL)
  546.         SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  547.     /* ----------- hide this window ------------ */
  548.     SendMessage(wnd, HIDE_WINDOW, TRUE, 0);
  549.     /* --- close the children of this window --- */
  550.     while (wnd->ChildCt)    {
  551.         WINDOW wnd1 = *(wnd->Children+wnd->ChildCt-1);
  552.         if (inFocus == wnd1)    {
  553.             RemoveFocusWindow(wnd);
  554.             AppendFocusWindow(wnd);
  555.             inFocus = wnd;
  556.         }
  557.         SendMessage(wnd1,CLOSE_WINDOW,0,0);
  558.     }
  559.     /* --- change focus if this window had it -- */
  560.     SetPrevFocus(wnd);
  561.     /* ------- remove this window from the
  562.             list of in-focus windows ---------- */
  563.     RemoveFocusWindow(wnd);
  564.     /* -- free memory allocated to this window - */
  565.     if (wnd->title != NULL)
  566.         free(wnd->title);
  567.     if (wnd->videosave != NULL)
  568.         free(wnd->videosave);
  569.     if (wnd->ChildCt)
  570.         free(wnd->Children);
  571.     /* -- remove window from parent's list of children -- */
  572.     if (pwnd != NULL && pwnd->ChildCt)    {
  573.         int i;
  574.         for (i = pwnd->ChildCt; i > 0; --i)
  575.             if (*(pwnd->Children+i-1) == wnd)    {
  576.                 --i;
  577.                 break;
  578.             }
  579.         for (; i < pwnd->ChildCt; i++)    
  580.             *(pwnd->Children+i) = *(pwnd->Children+i+1);
  581.         pwnd->ChildCt--;
  582.         pwnd->Children = realloc(pwnd->Children,
  583.             sizeof(WINDOW) * pwnd->ChildCt);
  584.     }
  585.     if (wnd == inFocus)
  586.         inFocus = NULL;
  587.     free(wnd);
  588. }
  589.  
  590. /* ---- Window-processing module for NORMAL window class ---- */
  591. int NormalProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  592. {
  593.     switch (msg)    {
  594.         case CREATE_WINDOW:
  595.             CreateWindowMsg(wnd);
  596.             break;
  597.         case SHOW_WINDOW:
  598.             ShowWindowMsg(wnd, p1, p2);
  599.             break;
  600.         case HIDE_WINDOW:
  601.             HideWindowMsg(wnd, (BOOL) p1);
  602.             break;
  603.         case DISPLAY_HELP:
  604.             DisplayHelp(wnd, (char *)p1);
  605.             break;
  606.         case INSIDE_WINDOW:
  607.             return InsideWindow(wnd, (int) p1, (int) p2);
  608.         case KEYBOARD:
  609.             if (KeyboardMsg(wnd, p1, p2))
  610.                 return TRUE;
  611.             /* ------- fall through ------- */
  612.         case ADDSTATUS:
  613.         case SHIFT_CHANGED:
  614.             if (GetParent(wnd) != NULL)
  615.                 PostMessage(GetParent(wnd), msg, p1, p2);
  616.             break;
  617.         case PAINT:
  618.             if (isVisible(wnd))    
  619.                 ClearWindow(wnd, (RECT *)p1, ' ');
  620.             break;
  621.         case BORDER:
  622.             if (isVisible(wnd))    {
  623.                 if (TestAttribute(wnd, HASBORDER))
  624.                     RepaintBorder(wnd, (RECT *)p1);
  625.                 else if (TestAttribute(wnd, HASTITLEBAR))
  626.                     DisplayTitle(wnd, (RECT *)p1);
  627.             }
  628.             break;
  629.         case COMMAND:
  630.             CommandMsg(wnd, p1);
  631.             break;
  632.         case SETFOCUS:
  633.             SetFocusMsg(wnd, p1);
  634.             break;
  635.         case DOUBLE_CLICK:
  636.             DoubleClickMsg(wnd, p1, p2);
  637.             break;
  638.         case LEFT_BUTTON:
  639.             LeftButtonMsg(wnd, p1, p2);
  640.             break;
  641.         case MOUSE_MOVED:
  642.             if (MouseMovedMsg(wnd, p1, p2))
  643.                 return TRUE;
  644.             break;
  645.         case BUTTON_RELEASED:
  646.             if (WindowMoving || WindowSizing)    {
  647.                 if (WindowMoving)
  648.                     PostMessage(wnd,MOVE,dwnd.rc.lf,dwnd.rc.tp);
  649.                 else
  650.                     PostMessage(wnd,SIZE,dwnd.rc.rt,dwnd.rc.bt);
  651.                 TerminateMoveSize();
  652.             }
  653.             break;
  654. #ifdef INCLUDE_MAXIMIZE
  655.         case MAXIMIZE:
  656.             if (wnd->condition != ISMAXIMIZED)
  657.                 MaximizeMsg(wnd);
  658.             break;
  659. #endif
  660. #ifdef INCLUDE_MINIMIZE
  661.         case MINIMIZE:
  662.             if (wnd->condition != ISMINIMIZED)
  663.                 MinimizeMsg(wnd);
  664.             break;
  665. #endif
  666. #ifdef INCLUDE_RESTORE
  667.         case RESTORE:
  668.             if (wnd->condition != ISRESTORED)    {
  669. #ifdef INCLUDE_MAXIMIZE
  670.                 if (wnd->oldcondition == ISMAXIMIZED)
  671.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  672.                 else
  673. #endif
  674.                     RestoreMsg(wnd);
  675.             }
  676.             break;
  677. #endif
  678.         case MOVE:
  679.             MoveMsg(wnd, p1, p2);
  680.             break;
  681.         case SIZE:    {
  682.             SizeMsg(wnd, p1, p2);
  683.             break;
  684.         }
  685.         case CLOSE_WINDOW:
  686.             CloseWindowMsg(wnd);
  687.             break;
  688.         default:
  689.             break;
  690.     }
  691.     return TRUE;
  692. }
  693. #ifdef INCLUDE_MINIMIZE
  694. /* ---- compute lower left icon space in a rectangle ---- */
  695. static RECT LowerRight(RECT prc)
  696. {
  697.     RECT rc;
  698.     RectLeft(rc) = RectRight(prc) - ICONWIDTH;
  699.     RectTop(rc) = RectBottom(prc) - ICONHEIGHT;
  700.     RectRight(rc) = RectLeft(rc)+ICONWIDTH-1;
  701.     RectBottom(rc) = RectTop(rc)+ICONHEIGHT-1;
  702.     return rc;
  703. }
  704. /* ----- compute a position for a minimized window icon ---- */
  705. static RECT PositionIcon(WINDOW wnd)
  706. {
  707.     RECT rc;
  708.     RectLeft(rc) = SCREENWIDTH-ICONWIDTH;
  709.     RectTop(rc) = SCREENHEIGHT-ICONHEIGHT;
  710.     RectRight(rc) = SCREENWIDTH-1;
  711.     RectBottom(rc) = SCREENHEIGHT-1;
  712.     if (GetParent(wnd))    {
  713.         WINDOW cwnd = (WINDOW) -1;
  714.         RECT prc;
  715.         int i;
  716.         prc = WindowRect(GetParent(wnd));
  717.         rc = LowerRight(prc);
  718.         /* - search for icon available location - */
  719.         for (i = 0; i < wnd->ChildCt; i++)    {
  720.             cwnd = *(wnd->Children + i);
  721.             if (cwnd->condition == ISMINIMIZED)    {
  722.                 RECT rc1;
  723.                 rc1 = WindowRect(cwnd);
  724.                 if (RectLeft(rc1) == RectLeft(rc) &&
  725.                         RectTop(rc1) == RectTop(rc))    {
  726.                     RectLeft(rc) -= ICONWIDTH;
  727.                     RectRight(rc) -= ICONWIDTH;
  728.                     if (RectLeft(rc) < RectLeft(prc)+1)   {
  729.                         RectLeft(rc) =
  730.                             RectRight(prc)-ICONWIDTH;
  731.                         RectRight(rc) =
  732.                             RectLeft(rc)+ICONWIDTH-1;
  733.                         RectTop(rc) -= ICONHEIGHT;
  734.                         RectBottom(rc) -= ICONHEIGHT;
  735.                         if (RectTop(rc) < RectTop(prc)+1)
  736.                             return LowerRight(prc);
  737.                     }
  738.                     break;
  739.                 }
  740.             }
  741.         }
  742.     }
  743.     return rc;
  744. }
  745. #endif
  746. /* ----- terminate the move or size operation ----- */
  747. static void TerminateMoveSize(void)
  748. {
  749.     px = py = -1;
  750.     diff = 0;
  751.     SendMessage(&dwnd, RELEASE_MOUSE, TRUE, 0);
  752.     SendMessage(&dwnd, RELEASE_KEYBOARD, TRUE, 0);
  753.     RestoreBorder(dwnd.rc);
  754.     WindowMoving = WindowSizing = FALSE;
  755. }
  756. /* ---- build a dummy window border for moving or sizing --- */
  757. static void near dragborder(WINDOW wnd, int x, int y)
  758. {
  759.     RestoreBorder(dwnd.rc);
  760.     /* ------- build the dummy window -------- */
  761.     dwnd.rc.lf = x;
  762.     dwnd.rc.tp = y;
  763.     dwnd.rc.rt = dwnd.rc.lf+WindowWidth(wnd)-1;
  764.     dwnd.rc.bt = dwnd.rc.tp+WindowHeight(wnd)-1;
  765.     dwnd.ht = WindowHeight(wnd);
  766.     dwnd.wd = WindowWidth(wnd);
  767.     dwnd.parent = GetParent(wnd);
  768.     dwnd.attrib = VISIBLE | HASBORDER | NOCLIP;
  769.     InitWindowColors(&dwnd);
  770.     SaveBorder(dwnd.rc);
  771.     RepaintBorder(&dwnd, NULL);
  772. }
  773. /* ---- write the dummy window border for sizing ---- */
  774. static void near sizeborder(WINDOW wnd, int rt, int bt)
  775. {
  776.     int leftmost = GetLeft(wnd)+10;
  777.     int topmost = GetTop(wnd)+3;
  778.     int bottommost = SCREENHEIGHT-1;
  779.     int rightmost  = SCREENWIDTH-1;
  780.     if (GetParent(wnd))    {
  781.         bottommost = min(bottommost,
  782.             GetClientBottom(GetParent(wnd)));
  783.         rightmost  = min(rightmost,
  784.             GetClientRight(GetParent(wnd)));
  785.     }
  786.     rt = min(rt, rightmost);
  787.     bt = min(bt, bottommost);
  788.     rt = max(rt, leftmost);
  789.     bt = max(bt, topmost);
  790.     SendMessage(NULL, MOUSE_CURSOR, rt, bt);
  791.  
  792.     if (rt != px || bt != py)
  793.         RestoreBorder(dwnd.rc);
  794.  
  795.     /* ------- change the dummy window -------- */
  796.     dwnd.ht = bt-dwnd.rc.tp+1;
  797.     dwnd.wd = rt-dwnd.rc.lf+1;
  798.     dwnd.rc.rt = rt;
  799.     dwnd.rc.bt = bt;
  800.     if (rt != px || bt != py)    {
  801.         px = rt;
  802.         py = bt;
  803.         SaveBorder(dwnd.rc);
  804.         RepaintBorder(&dwnd, NULL);
  805.     }
  806. }
  807. #ifdef INCLUDE_MULTI_WINDOWS
  808. /* ----- adjust a rectangle to include the shadow ----- */
  809. static RECT adjShadow(WINDOW wnd)
  810. {
  811.     RECT rc;
  812.     rc = wnd->rc;
  813.     if (TestAttribute(wnd, SHADOW))    {
  814.         if (RectRight(rc) < SCREENWIDTH-1)
  815.             RectRight(rc)++;           
  816.         if (RectBottom(rc) < SCREENHEIGHT-1)
  817.             RectBottom(rc)++;
  818.     }
  819.     return rc;
  820. }
  821. /* --- repaint a rectangular subsection of a window --- */
  822. static void near PaintOverLap(WINDOW wnd, RECT rc)
  823. {
  824.     if (isVisible(wnd))    {
  825.         int isBorder, isTitle, isData;
  826.         isBorder = isTitle = FALSE;
  827.         isData = TRUE;
  828.         if (TestAttribute(wnd, HASBORDER))    {
  829.             isBorder =  RectLeft(rc) == 0 &&
  830.                         RectTop(rc) < WindowHeight(wnd);
  831.             isBorder |= RectLeft(rc) < WindowWidth(wnd) &&
  832.                         RectRight(rc) >= WindowWidth(wnd)-1 &&
  833.                         RectTop(rc) < WindowHeight(wnd);
  834.             isBorder |= RectTop(rc) == 0 &&
  835.                         RectLeft(rc) < WindowWidth(wnd);
  836.             isBorder |= RectTop(rc) < WindowHeight(wnd) &&
  837.                         RectBottom(rc) >= WindowHeight(wnd)-1 &&
  838.                         RectLeft(rc) < WindowWidth(wnd);
  839.         }
  840.         else if (TestAttribute(wnd, HASTITLEBAR))
  841.             isTitle = RectTop(rc) == 0 &&
  842.                       RectLeft(rc) > 0 &&
  843.                       RectLeft(rc)<WindowWidth(wnd)-BorderAdj(wnd);
  844.  
  845.         if (RectLeft(rc) >= WindowWidth(wnd)-BorderAdj(wnd))
  846.             isData = FALSE;
  847.         if (RectTop(rc) >= WindowHeight(wnd)-BottomBorderAdj(wnd))
  848.             isData = FALSE;
  849.         if (TestAttribute(wnd, HASBORDER))    {
  850.             if (RectRight(rc) == 0)
  851.                 isData = FALSE;
  852.             if (RectBottom(rc) == 0)
  853.                 isData = FALSE;
  854.         }
  855.         if (TestAttribute(wnd, SHADOW))
  856.             isBorder |= RectRight(rc) == WindowWidth(wnd) ||
  857.                         RectBottom(rc) == WindowHeight(wnd);
  858.         if (isData)
  859.             SendMessage(wnd, PAINT, (PARAM) &rc, TRUE);
  860.         if (isBorder)
  861.             SendMessage(wnd, BORDER, (PARAM) &rc, 0);
  862.         else if (isTitle)
  863.             DisplayTitle(wnd, &rc);
  864.     }
  865. }
  866. /* ------ paint the part of a window that is overlapped
  867.             by another window that is being hidden ------- */
  868. static void PaintOver(WINDOW wnd)
  869. {
  870.     RECT wrc, rc;
  871.     wrc = adjShadow(HiddenWindow);
  872.     rc = adjShadow(wnd);
  873.     rc = subRectangle(rc, wrc);
  874.     if (ValidRect(rc))
  875.         PaintOverLap(wnd, RelativeWindowRect(wnd, rc));
  876. }
  877. /* --- paint the overlapped parts of all children --- */
  878. static void PaintOverChildren(WINDOW pwnd)
  879. {
  880.     WINDOW cwnd = GetFirstFocusChild(pwnd);
  881.     while (cwnd != NULL)    {
  882.         if (cwnd != HiddenWindow)    {
  883.             PaintOver(cwnd);
  884.             PaintOverChildren(cwnd);
  885.         }
  886.         cwnd = GetNextFocusChild(pwnd, cwnd);
  887.     }
  888. }
  889. /* -- recursive overlapping paint of parents -- */
  890. static void PaintOverParents(WINDOW wnd)
  891. {
  892.     WINDOW pwnd = GetParent(wnd);
  893.     if (pwnd != NULL)    {
  894.         PaintOverParents(pwnd);
  895.         PaintOver(pwnd);
  896.         PaintOverChildren(pwnd);
  897.     }
  898. }
  899. /* - paint the parts of all windows that a window is over - */
  900. static void near PaintOverLappers(WINDOW wnd)
  901. {
  902.     HiddenWindow = wnd;
  903.     PaintOverParents(wnd);
  904. }
  905. /* --- paint those parts of a window that are overlapped --- */
  906. static void near PaintUnderLappers(WINDOW wnd)
  907. {
  908.     WINDOW hwnd = NextWindow(wnd);
  909.     while (hwnd != NULL)    {
  910.         /* ------- test only at document window level ------ */
  911.         WINDOW pwnd = GetParent(hwnd);
  912.         if (pwnd == NULL || GetClass(pwnd) == APPLICATION)    {
  913.             /* ---- don't bother testing self ----- */
  914.             if (isVisible(hwnd) && hwnd != wnd)    {
  915.                 /* --- see if other window is descendent --- */
  916.                 while (pwnd != NULL)    {
  917.                     if (pwnd == wnd)
  918.                         break;
  919.                     pwnd = GetParent(pwnd);
  920.                 }
  921.                 /* ----- don't test descendent overlaps ----- */
  922.                 if (pwnd == NULL)    {
  923.                     /* -- see if other window is ancestor --- */
  924.                     pwnd = GetParent(wnd);
  925.                     while (pwnd != NULL)    {
  926.                         if (pwnd == hwnd)
  927.                             break;
  928.                         pwnd = GetParent(pwnd);
  929.                     }
  930.                     /* --- don't test ancestor overlaps --- */
  931.                     if (pwnd == NULL)    {
  932.                         HiddenWindow = GetAncestor(hwnd);
  933.                         ClearVisible(HiddenWindow);
  934.                         PaintOver(wnd);
  935.                         SetVisible(HiddenWindow);
  936.                     }
  937.                 }
  938.             }
  939.         }
  940.         hwnd = NextWindow(hwnd);
  941.     }
  942.     /* --------- repaint all children of this window
  943.         the same way ----------- */
  944.     hwnd = Focus.FirstWindow;
  945.     while (hwnd != NULL)    {
  946.         if (GetParent(hwnd) == wnd)
  947.             PaintUnderLappers(hwnd);
  948.         hwnd = NextWindow(hwnd);
  949.     }
  950. }
  951. #endif /* #ifdef INCLUDE_MULTI_WINDOWS */
  952.  
  953. /* --- save video area to be used by dummy window border --- */
  954. static void SaveBorder(RECT rc)
  955. {
  956.     Bht = RectBottom(rc) - RectTop(rc) + 1;
  957.     Bwd = RectRight(rc) - RectLeft(rc) + 1;
  958.     if ((Bsave = realloc(Bsave, (Bht + Bwd) * 4)) != NULL)    {
  959.         RECT lrc;
  960.         int i;
  961.         int *cp;
  962.  
  963.         lrc = rc;
  964.         RectBottom(lrc) = RectTop(lrc);
  965.         getvideo(lrc, Bsave);
  966.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  967.         getvideo(lrc, Bsave + Bwd);
  968.         cp = Bsave + Bwd * 2;
  969.         for (i = 1; i < Bht-1; i++)    {
  970.             *cp++ = GetVideoChar(RectLeft(rc),RectTop(rc)+i);
  971.             *cp++ = GetVideoChar(RectRight(rc),RectTop(rc)+i);
  972.         }
  973.     }
  974. }
  975. /* ---- restore video area used by dummy window border ---- */
  976. static void RestoreBorder(RECT rc)
  977. {
  978.     if (Bsave != NULL)    {
  979.         RECT lrc;
  980.         int i;
  981.         int *cp;
  982.         lrc = rc;
  983.         RectBottom(lrc) = RectTop(lrc);
  984.         storevideo(lrc, Bsave);
  985.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  986.         storevideo(lrc, Bsave + Bwd);
  987.         cp = Bsave + Bwd * 2;
  988.         for (i = 1; i < Bht-1; i++)    {
  989.             PutVideoChar(RectLeft(rc),RectTop(rc)+i, *cp++);
  990.             PutVideoChar(RectRight(rc),RectTop(rc)+i, *cp++);
  991.         }
  992.         free(Bsave);
  993.         Bsave = NULL;
  994.     }
  995. }
  996. /* ----- test if screen coordinates are in a window ---- */
  997. static BOOL InsideWindow(WINDOW wnd, int x, int y)
  998. {
  999.     RECT rc;
  1000.     rc = WindowRect(wnd);
  1001.     if (!TestAttribute(wnd, NOCLIP))    {
  1002.         WINDOW pwnd = GetParent(wnd);
  1003.         while (pwnd != NULL)    {
  1004.             rc = subRectangle(rc, ClientRect(pwnd));
  1005.             pwnd = GetParent(pwnd);
  1006.         }
  1007.     }
  1008.     return InsideRect(x, y, rc);
  1009. }
  1010. /* ----- find window that screen coordinates are in --- */
  1011. WINDOW inWindow(int x, int y)
  1012. {
  1013.     WINDOW wnd = Focus.LastWindow;
  1014.     while (wnd != NULL)    {
  1015.         if (isVisible(wnd))    {
  1016.             if (SendMessage(wnd, INSIDE_WINDOW, x, y))    {
  1017.                 WINDOW wnd1;
  1018.                 int i;
  1019.                 for (i = wnd->ChildCt; i > 0; --i)    {
  1020.                     wnd1 = *(wnd->Children+i-1);
  1021.                     if (SendMessage(wnd1, INSIDE_WINDOW, x, y)) {
  1022.                         if (isVisible(wnd1))  {
  1023.                             wnd = wnd1;
  1024.                             break;
  1025.                         }
  1026.                     }
  1027.                 }
  1028.                 break;
  1029.             }
  1030.         }
  1031.         wnd = PrevWindow(wnd);
  1032.     }
  1033.     return wnd;
  1034. }
  1035.  
  1036. BOOL isDerivedFrom(WINDOW wnd, CLASS class)
  1037. {
  1038.     CLASS tclass = GetClass(wnd);
  1039.     while (tclass != -1)    {
  1040.         if (tclass == class)
  1041.             return TRUE;
  1042.         tclass = (classdefs[tclass].base);
  1043.     }
  1044.     return FALSE;
  1045. }
  1046.  
  1047. /* -- find the oldest document window ancestor of a window -- */
  1048. WINDOW GetAncestor(WINDOW wnd)
  1049. {
  1050.     if (wnd != NULL)    {
  1051.         while (GetParent(wnd) != NULL)    {
  1052.             if (GetClass(GetParent(wnd)) == APPLICATION)
  1053.                 break;
  1054.             wnd = GetParent(wnd);
  1055.         }
  1056.     }
  1057.     return wnd;
  1058. }
  1059.  
  1060. BOOL isVisible(WINDOW wnd)
  1061. {
  1062.     while (wnd != NULL)    {
  1063.         if (isHidden(wnd))
  1064.             return FALSE;
  1065.         wnd = GetParent(wnd);
  1066.     }
  1067.     return TRUE;
  1068. }
  1069.  
  1070.  
  1071.